package testcasegeneration

import (
	"bufio"
	"fmt"
	"myOJ/coderun"
	"myOJ/datastructure"

	"myOJ/db"
	"os"
	"strconv"
	"strings"

	"github.com/google/uuid"
)

//选择合适的生成器生成单个参数的输入样例字符串
func selectGenAndCreate(argType string, scale int) string {
	typeAndOtherInfo := strings.Split(argType, "#")
	atype := typeAndOtherInfo[0]

	var dataLen int = 500 / testNUM * scale
	if len(typeAndOtherInfo) > 1 {
		dataLen, _ = strconv.Atoi(typeAndOtherInfo[1])
		dataLen = dataLen / testNUM * scale
	}

	switch atype {
	case "int":
		return randomInt(0, dataLen)

	case "Array<01>":
		return array01(dataLen)
	case "Array<int>":
		return randomArray(dataLen)
	case "string":
		return randomString(dataLen)
	case "LINKEDLIST":
		return linkedList(dataLen)
	case "BTREE":
		return binaryTree(dataLen)
	}
	return ""
}

//解析生的参数类型，返回随机的测试样例
func genInputTest(rowArgsFormatString string, scale int) string {
	rowArgs := strings.Split(rowArgsFormatString, ";")

	inputTest := ""
	for i := range rowArgs {
		argNameAndType := strings.Split(rowArgs[i], ":")
		// argName := argNameAndType[0]
		argType := argNameAndType[1]

		inputTest += selectGenAndCreate(argType, scale)

		if i != len(rowArgs)-1 {
			inputTest += ","
		}
	}
	return inputTest
}

//根据正确代码生成输出样例
func getTemplate() string {
	file, err := os.Open("testcasegeneration/pymain")
	if err != nil {
		fmt.Println("Open testcasegeneration/pymain ", err)
		panic(err)
	}
	defer file.Close()
	r := bufio.NewReader(file)

	buf := make([]byte, 128)
	r.Read(buf)

	return string(buf)
}

var fileroot string = "excefileroot/"

func genOutputTest(code string, inputTest string) string {
	randomSeed := uuid.New().String()

	filename := fileroot + randomSeed + ".py"

	file, _ := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0777)
	defer file.Close()

	mainTemplate := getTemplate()

	file.Write([]byte(code + strings.ReplaceAll(mainTemplate, "*theArgs", inputTest)))

	args := make([]string, 0)
	args = append(args, filename)
	return coderun.Runpy(args)

}

//添加样例到数据库
var testNUM int = 20

func GenTest(pp datastructure.ProblemPost) {
	ptitle := pp.Ptitle
	rowArgsFormatString := pp.Args
	answercode := pp.AnswerCode
	for i := 0; i < testNUM; i++ {
		inputTest := genInputTest(rowArgsFormatString, i+1)
		outputTest := genOutputTest(answercode, inputTest)
		db.PushCodeTestcase(ptitle, inputTest, outputTest)
	}
}
